package com.linkoog.devtools.archive.filesystem;


import com.intellij.openapi.fileTypes.FileNameMatcher;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem;
import com.intellij.openapi.vfs.newvfs.VfsImplUtil;
import com.linkoog.devtools.archive.filesystem.zip.ArchiveFileTypeExt;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

/**
 */
public abstract class ArchiveBasedFileSystem extends ArchiveFileSystem {

    public static final String SEPARATOR = "!/";

    public static boolean isValid(String path) {
        return path.contains(SEPARATOR);
    }

    public static boolean containExtension(@NotNull String path) {
        FileTypeManager typeManager = FileTypeManager.getInstance();
        List<FileNameMatcher> matchers = new ArrayList<>();
        matchers.addAll(typeManager.getAssociations(com.intellij.ide.highlighter.ArchiveFileType.INSTANCE));
        matchers.addAll(typeManager.getAssociations(ArchiveFileTypeExt.INSTANCE));

        for (FileNameMatcher matcher : matchers) {
            if (matcher.acceptsCharSequence(path)){
                return true;
            }
        }
        return false;
    }

    public static boolean isNestedFile(@NotNull String path) {
        if (StringUtils.countMatches(path, SEPARATOR) > 0) {
            if (containExtension(path)) {
                return true;
            }
        }

        return false;
    }


    @Override
    protected String composeRootPath(@NotNull String localPath) {
        return localPath + SEPARATOR;
    }

    @Override
    protected String extractLocalPath(@NotNull String rootPath) {
        return StringUtil.trimEnd(rootPath, SEPARATOR);
    }

    @Override
    protected String extractRootPath(@NotNull String path) {
        final int jarSeparatorIndex = path.indexOf(SEPARATOR);
        assert jarSeparatorIndex >= 0: "Path passed to ${this.class} must have separator '${separator}': " + path;
        return path.substring(0, jarSeparatorIndex + SEPARATOR.length());
    }

    @Override
    public VirtualFile findFileByPathIfCached(@NotNull String path) {
        return isValid(path) ? VfsImplUtil.findFileByPathIfCached(this, path) : null;
    }

    @Override
    public VirtualFile findFileByPath(@NotNull String path) {
        return isValid(path) ? VfsImplUtil.findFileByPath(this, path) : null;
    }

    @Override
    public void refresh(boolean asynchronous) {
        VfsImplUtil.refresh(this, asynchronous);
    }

    @Override
    public VirtualFile refreshAndFindFileByPath(@NotNull String path) {
        return isValid(path) ? VfsImplUtil.refreshAndFindFileByPath(this, path) : null;
    }

    @NotNull
    @Override
    public String normalize(@NotNull String path) {
        int p = path.indexOf(SEPARATOR);
        return p > 0 ? FileUtil.normalize(path.substring(0, p)) + path.substring(p) : path;
    }
}